package com.anlogic.sdk.bsp.settings;

import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;

public class BspSettingsView extends TitleAreaDialog {
	private TreeViewer navigator;

	private Composite contentArea;

	private StackLayout contentStack;

	private NavItem navRoot;
	
	private NavItem navPlatform;

	private NavItem navDrivers;

	private NavItem navLibraries;

	private SummaryView summaryView;

	private ConfigView configView;
	
	private LibraryView libraryView;

	private DriversView driverView;
	
	private IBspSettingTool bspSettingTool;

	public BspSettingsView(Shell parentShell, IBspSettingTool bspSettingTool) {
		super(parentShell);
		setShellStyle(getShellStyle() | SWT.RESIZE);
		this.bspSettingTool = bspSettingTool;
	}

	protected Control createDialogArea(Composite parent) {
		setTitle("Board Support Package Settings");
		setMessage("Control various settings of your board support package.");

		Composite composite = new Composite(parent, SWT.NONE);
		composite.setLayout((Layout) new GridLayout(2, false));
		GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
		composite.setLayoutData(gd);
		createNavigator(composite);
		createContentArea(composite);
		return (Control) parent;
	}

	private void createNavigator(Composite parent) {
		this.navigator = new TreeViewer(parent, SWT.H_SCROLL | SWT.SINGLE);
		this.navigator.expandAll();
		GridData gd = new GridData(SWT.LEFT, SWT.FILL, false, false);
		this.navigator.getTree().setLayoutData(gd);
	}

	private void createContentArea(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setLayout((Layout) new GridLayout(1, false));
		GridData gd = new GridData(SWT.BEGINNING, SWT.TOP, true, true);
		composite.setLayoutData(gd);
		this.contentArea = new Composite(composite, SWT.NONE);
		this.contentStack = new StackLayout();
		this.contentArea.setLayout((Layout) this.contentStack);
		this.contentArea.setLayoutData(new GridData(SWT.DOWN | SWT.V_SCROLL | SWT.H_SCROLL | SWT.RESIZE));
		this.summaryView = new SummaryView(this, this.contentArea, this.bspSettingTool);
		this.libraryView = new LibraryView(this, this.contentArea, this.bspSettingTool);
		this.configView = new ConfigView(this, this.contentArea, this.bspSettingTool);
		this.driverView = new DriversView(this, this.contentArea, this.bspSettingTool);
		setContentStackTop(Constants.CONTENT_TYPE_SUMMARY);
		viewReady();
	}
	
	protected void okPressed() {
		super.okPressed();
		bspSettingTool.regenerateBsp();
	}

	public void setContentStackTop(int id) {
		switch (id) {
		case Constants.CONTENT_TYPE_SUMMARY:
			this.contentStack.topControl = (Control) this.summaryView.getContent();
			break;
		case Constants.CONTENT_TYPE_DRIVER:
			this.contentStack.topControl = (Control) this.driverView.getContent();
			break;
		case Constants.CONTENT_TYPE_LIBRARY:
			this.contentStack.topControl = (Control) this.libraryView.getContent();
			break;
		case Constants.CONTENT_TYPE_PLATFORM:
			this.contentStack.topControl = (Control) this.configView.getContent();
			break;
		case Constants.CONTENT_TYPE_OS:
			this.contentStack.topControl = (Control) this.configView.getContent();
			break;
		case Constants.CONTENT_TYPE_CONFIG:
			this.contentStack.topControl = (Control) this.configView.getContent();
			break;
		default:
			this.contentStack.topControl = (Control) this.summaryView.getContent();
			break;
		}
		this.contentArea.layout();
	}

	private void createNavItems() {
		this.navRoot = new NavItem("Overview");
		this.navRoot.setContentType(Constants.CONTENT_TYPE_SUMMARY);
		String osName = this.bspSettingTool.getBspOsInfo().getName();
		if (this.bspSettingTool.isConfigurable(osName) && this.configView.addConfig(osName, Constants.COMPONET_TYPE_OS)) {
			NavItem c = new NavItem(osName);
			c.setContentType(Constants.CONTENT_TYPE_OS);
			this.navRoot.addChild(c);
		}
		if (this.configView.addConfig("config", Constants.COMPONET_TYPE_PLATFORM)) {
			this.navPlatform = new NavItem("platform");
			this.navPlatform.setContentType(Constants.CONTENT_TYPE_PLATFORM);
			this.navRoot.addChild(this.navPlatform);
		}
		this.navDrivers = new NavItem("driver");
		this.navDrivers.setContentType(Constants.CONTENT_TYPE_DRIVER);
		this.navRoot.addChild(this.navDrivers);
		this.navLibraries = new NavItem("library");
		this.navLibraries.setContentType(Constants.CONTENT_TYPE_LIBRARY);
		this.navRoot.addChild(this.navLibraries);
	}

	public void viewReady() {
		createNavItems();
		NavInfoProvider navInfoProvider = new NavInfoProvider();
		this.setNavInfoProviders(navInfoProvider, navInfoProvider);
		this.setNavigatorListener(new NavSelectionListener());
		this.summaryView.viewReady();
		this.driverView.viewReady();
		this.libraryView.viewReady();
		this.refreshNavigator("");
	}

	public void setNavInfoProviders(ITreeContentProvider cp, ILabelProvider lp) {
		this.navigator.setContentProvider((IContentProvider) cp);
		this.navigator.setLabelProvider((IBaseLabelProvider) lp);
	}

	public void setNavigatorListener(ISelectionChangedListener l) {
		this.navigator.addSelectionChangedListener(l);
	}

	public void refreshNavigator(Object input) {
		this.navigator.setInput(input);
		this.navigator.expandAll();
	}

	public void addLibraryChild(String libprefix) {
		if (!this.configView.addConfig(libprefix, Constants.COMPONET_TYPE_LIBRARY))
			return;
		NavItem c = new NavItem(libprefix);
		c.setContentType(Constants.CONTENT_TYPE_CONFIG);
		this.navLibraries.addChild(c);
		this.refreshNavigator("");
	}

	public void removeLibraryChild(String libprefix) {
		List<NavItem> children = this.navLibraries.getChildren();
		Iterator<NavItem> itr = children.iterator();
		NavItem r = null;
		while (itr.hasNext()) {
			NavItem n = itr.next();
			if (n.getName().startsWith(libprefix))
				r = n;
		}
		if (r != null) {
			this.navLibraries.removeChild(r);
			this.refreshNavigator("");
		}
		this.configView.removeConfig(libprefix, Constants.COMPONET_TYPE_LIBRARY);
	}

	class NavInfoProvider extends LabelProvider implements ITreeContentProvider {
		@Override
		public Object[] getChildren(Object parentElement) {
			if (!(parentElement instanceof NavItem))
				return new Object[0];
			NavItem n = (NavItem) parentElement;
			return n.getChildren().toArray((Object[]) new NavItem[0]);
		}

		@Override
		public Object getParent(Object element) {
			if (!(element instanceof NavItem))
				return null;
			NavItem n = (NavItem) element;
			return n.getParent();
		}

		@Override
		public boolean hasChildren(Object element) {
			if (!(element instanceof NavItem))
				return false;
			NavItem n = (NavItem) element;
			return (n.getChildren().size() != 0);
		}

		public void dispose() {
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}

		public String getText(Object element) {
			if (!(element instanceof NavItem))
				return "";
			NavItem n = (NavItem) element;
			return n.getName();
		}

		@Override
		public Object[] getElements(Object inputElement) {
			if (inputElement instanceof String)
				return new Object[] { navRoot };
			return getChildren(inputElement);
		}
	}

	class NavSelectionListener implements ISelectionChangedListener {
		public void selectionChanged(SelectionChangedEvent event) {
			if (!(event.getSelection() instanceof IStructuredSelection))
				return;
			IStructuredSelection selection = (IStructuredSelection) event.getSelection();
			if (!(selection.getFirstElement() instanceof NavItem))
				return;
			NavItem item = (NavItem) selection.getFirstElement();
			setContentStackTop(item.getContentType());
			if (item.getContentType() == Constants.CONTENT_TYPE_CONFIG) {
				configView.setCurrentConfig(item.getName());
			}
			if (item.getContentType() == Constants.CONTENT_TYPE_PLATFORM) {
				configView.setCurrentConfig("config");
			}
			if (item.getContentType() == Constants.CONTENT_TYPE_OS) {
				configView.setCurrentConfig(BspSettingsView.this.bspSettingTool.getBspOsInfo().getName());
			}
		}
	}
}